﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Xml.Linq;
using DCT.Model;
using System.Reflection;

namespace DCT.ViewModel
{
    public class Utilities
    {
        public static bool CompareID(string id1, string id2)
        {
            UInt32 unsignedID1, unsignedID2;
            if (string.IsNullOrEmpty(id1) || string.IsNullOrEmpty(id2))
            {
                return false;
            }

            try
            {
                unsignedID1 = Convert.ToUInt32(id1, 16);
                unsignedID2 = Convert.ToUInt32(id2, 16);
            }
            catch
            {
                return false;
            }

            return unsignedID1 == unsignedID2;
        }

        public static bool CompareID(string id1, int id2)
        {
            Int32 intID1;
            if (string.IsNullOrEmpty(id1))
            {
                return false;
            }

            try
            {
                intID1 = Convert.ToInt32(id1, 16);
            }
            catch
            {
                return false;
            }

            return intID1 == id2;
        }

        public static XElement SerializeDeviceViewModel(DeviceBaseViewModel deviceViewModel)
        {
            Type deviceViewModelType = deviceViewModel.GetType();
            XElement root = new XElement(deviceViewModelType.Name);

            foreach(PropertyInfo propertyInfo in deviceViewModelType.GetProperties())
            {
                root.Add(new XElement(propertyInfo.Name, propertyInfo.GetValue(deviceViewModel, null)));
            }

            return root;
        }

        //public static void DeserializeDeviceViewModelChanges(XElement xmlChanges, )
        //{

        //}

        public static XElement SerializeDeviceViewModels(string deviceMapName, IEnumerable<DeviceBaseViewModel> deviceViewModels)
        {
            XElement serializedDeviceViewModels = new XElement(Resource.SerializeDeviceViewModels_Root,
                                                                new XAttribute(Resource.SerializeDeviceViewModels_Root_Attribute_DeviceMapName, deviceMapName));

            foreach (DeviceBaseViewModel deviceViewModel in deviceViewModels)
            {
                switch (deviceViewModel.GetType().Name)
                {
                    case "AxleViewModel":
                        AxleViewModel axViewModel = deviceViewModel as AxleViewModel;
                        serializedDeviceViewModels.Add(new XElement(Resource.SerializeDeviceViewModels_Axle,
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_ID, axViewModel.AxleModel.DeviceID),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceType, axViewModel.AxleModel.DeviceType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_Name, axViewModel.AxleGraphModel.DeviceName),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_GraphType, axViewModel.AxleGraphModel.GraphType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_PositionPoint, axViewModel.AxleGraphModel.PositionPoint),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceAngle, axViewModel.AxleGraphModel.DeviceAngle),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceWidth, axViewModel.AxleGraphModel.DeviceWidth),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceHeight, axViewModel.AxleGraphModel.DeviceHeight)
                                                            ));
                        break;
                    case "MiscellaneousDeviceViewModel":
                        MiscellaneousDeviceViewModel mdViewModel = deviceViewModel as MiscellaneousDeviceViewModel;
                        serializedDeviceViewModels.Add(new XElement(Resource.SerializeDeviceViewModels_MD,
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_ID, mdViewModel.MDModel.DeviceID),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceType, mdViewModel.MDModel.DeviceType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_Name, mdViewModel.MDGraphModel.DeviceName),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_GraphType, mdViewModel.MDGraphModel.GraphType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_PositionPoint, mdViewModel.MDGraphModel.PositionPoint),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceAngle, mdViewModel.MDGraphModel.DeviceAngle),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceWidth, mdViewModel.MDGraphModel.DeviceWidth),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceHeight, mdViewModel.MDGraphModel.DeviceHeight),
                                                            new XElement(Resource.SerializeDeviceViewModels_MD_MDBitmap, mdViewModel.MDGraphModel.MDBitmap),
                                                            new XElement(Resource.SerializeDeviceViewModels_MD_MDString, mdViewModel.MDGraphModel.MDString),
                                                            new XElement(Resource.SerializeDeviceViewModels_MD_MDSubType, mdViewModel.MDModel.MDSubType)
                                                            ));
                        break;
                    case "PlatformViewModel":
                        PlatformViewModel pfViewModel = deviceViewModel as PlatformViewModel;
                        serializedDeviceViewModels.Add(new XElement(Resource.SerializeDeviceViewModels_Platform,
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_ID, pfViewModel.PlatformModel.DeviceID),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceType, pfViewModel.PlatformModel.DeviceType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_Name, pfViewModel.PlatformGraphModel.DeviceName),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_GraphType, pfViewModel.PlatformGraphModel.GraphType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_PositionPoint, pfViewModel.PlatformGraphModel.PositionPoint),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceAngle, pfViewModel.PlatformGraphModel.DeviceAngle),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceWidth, pfViewModel.PlatformGraphModel.DeviceWidth),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceHeight, pfViewModel.PlatformGraphModel.DeviceHeight)
                                                            ));
                        break;
                    case "SignalViewModel":
                        SignalViewModel sgViewModel = deviceViewModel as SignalViewModel;
                        serializedDeviceViewModels.Add(new XElement(Resource.SerializeDeviceViewModels_Signal,
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_ID, sgViewModel.SignalModel.DeviceID),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceType, sgViewModel.SignalModel.DeviceType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_Name, sgViewModel.SignalGraphModel.DeviceName),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_GraphType, sgViewModel.SignalGraphModel.GraphType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_PositionPoint, sgViewModel.SignalGraphModel.PositionPoint),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceAngle, sgViewModel.SignalGraphModel.DeviceAngle),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceWidth, sgViewModel.SignalGraphModel.DeviceWidth),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceHeight, sgViewModel.SignalGraphModel.DeviceHeight)
                                                            ));
                        break;
                    case "SwitchViewModel":
                        SwitchViewModel swViewModel = deviceViewModel as SwitchViewModel;
                        serializedDeviceViewModels.Add(new XElement(Resource.SerializeDeviceViewModels_Switch,
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_ID, swViewModel.SwitchModel.DeviceID),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceType, swViewModel.SwitchModel.DeviceType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_Name, swViewModel.SwitchGraphModel.DeviceName),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_GraphType, swViewModel.SwitchGraphModel.GraphType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceAngle, swViewModel.SwitchGraphModel.DeviceAngle),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceWidth, swViewModel.SwitchGraphModel.DeviceWidth),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceHeight, swViewModel.SwitchGraphModel.DeviceHeight),
                                                            new XElement(Resource.SerializeDeviceViewModels_Switch_MergePoint, swViewModel.SwitchGraphModel.MergePoint),
                                                            new XElement(Resource.SerializeDeviceViewModels_Switch_NormalPoint, swViewModel.SwitchGraphModel.NormalPoint),
                                                            new XElement(Resource.SerializeDeviceViewModels_Switch_ReversePoint, swViewModel.SwitchGraphModel.ReversePoint)
                                                            ));
                        break;
                    case "TrackSegmentViewModel":
                        TrackSegmentViewModel tsViewModel = deviceViewModel as TrackSegmentViewModel;
                        serializedDeviceViewModels.Add(new XElement(Resource.SerializeDeviceViewModels_TrackSegment,
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_ID, tsViewModel.TrackSegmentModel.DeviceID),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceType, tsViewModel.TrackSegmentModel.DeviceType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_Name, tsViewModel.TrackSegmentGraphModel.DeviceName),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_GraphType, tsViewModel.TrackSegmentGraphModel.GraphType),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceAngle, tsViewModel.TrackSegmentGraphModel.DeviceAngle),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceWidth, tsViewModel.TrackSegmentGraphModel.DeviceWidth),
                                                            new XElement(Resource.SerializeDeviceViewModels_Device_DeviceHeight, tsViewModel.TrackSegmentGraphModel.DeviceHeight),
                                                            new XElement(Resource.SerializeDeviceViewModels_TrackSegment_StartPoint, tsViewModel.TrackSegmentGraphModel.StartPoint),
                                                            new XElement(Resource.SerializeDeviceViewModels_TrackSegment_EndPoint, tsViewModel.TrackSegmentGraphModel.EndPoint)
                                                            ));
                        break;
                    default:
                        break;
                }
            }

            return serializedDeviceViewModels;
        }

        public static List<DeviceBaseViewModel> DeserializeDeviceViewModels(string deviceMapName, XElement devicesXML, Point offset)
        {
            List<DeviceBaseViewModel> deviceViewModels = new List<DeviceBaseViewModel>();

            if ((string)devicesXML.Attribute(Resource.SerializeDeviceViewModels_Root_Attribute_DeviceMapName) == deviceMapName)
            {
                foreach (XElement deviceXML in devicesXML.Elements())
                {
                    if (deviceXML.Name.LocalName == Resource.SerializeDeviceViewModels_Axle)
                    {
                        deviceViewModels.AddRange(DeviceViewModelFactory.GenerateDeviceViewModel(new AxleModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceType)
                                                                                                     },
                                                                                                     new AxleGraphModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceName = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_Name),
                                                                                                         GraphType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_GraphType),
                                                                                                         PositionPoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_PositionPoint),
                                                                                                         DeviceAngle = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceAngle)),
                                                                                                         DeviceWidth = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceWidth)),
                                                                                                         DeviceHeight = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceHeight))
                                                                                                     }));
                    }
                    else if (deviceXML.Name.LocalName == Resource.SerializeDeviceViewModels_MD)
                    {
                        deviceViewModels.AddRange(DeviceViewModelFactory.GenerateDeviceViewModel(new MiscellaneousDeviceModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceType),
                                                                                                         MDSubType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_MD_MDSubType)
                                                                                                     },
                                                                                                     new MiscellaneousDeviceGraphModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceName = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_Name),
                                                                                                         GraphType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_GraphType),
                                                                                                         PositionPoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_PositionPoint),
                                                                                                         DeviceAngle = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceAngle)),
                                                                                                         DeviceWidth = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceWidth)),
                                                                                                         DeviceHeight = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceHeight)),
                                                                                                         MDBitmap = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_MD_MDBitmap),
                                                                                                         MDString = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_MD_MDString),
                                                                                                     }));
                    }
                    else if (deviceXML.Name.LocalName == Resource.SerializeDeviceViewModels_Platform)
                    {
                        deviceViewModels.AddRange(DeviceViewModelFactory.GenerateDeviceViewModel(new PlatformModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceType)
                                                                                                     },
                                                                                                     new PlatformGraphModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceName = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_Name),
                                                                                                         GraphType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_GraphType),
                                                                                                         PositionPoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_PositionPoint),
                                                                                                         DeviceAngle = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceAngle)),
                                                                                                         DeviceWidth = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceWidth)),
                                                                                                         DeviceHeight = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceHeight))
                                                                                                     }));
                    }
                    else if (deviceXML.Name.LocalName == Resource.SerializeDeviceViewModels_Signal)
                    {
                        deviceViewModels.AddRange(DeviceViewModelFactory.GenerateDeviceViewModel(new SignalModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceType)
                                                                                                     },
                                                                                                     new SignalGraphModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceName = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_Name),
                                                                                                         GraphType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_GraphType),
                                                                                                         PositionPoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_PositionPoint),
                                                                                                         DeviceAngle = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceAngle)),
                                                                                                         DeviceWidth = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceWidth)),
                                                                                                         DeviceHeight = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceHeight))
                                                                                                     }));
                    }
                    else if (deviceXML.Name.LocalName == Resource.SerializeDeviceViewModels_Switch)
                    {
                        deviceViewModels.AddRange(DeviceViewModelFactory.GenerateDeviceViewModel(new SwitchModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceType)
                                                                                                     },
                                                                                                     new SwitchGraphModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceName = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_Name),
                                                                                                         GraphType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_GraphType),
                                                                                                         DeviceAngle = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceAngle)),
                                                                                                         DeviceWidth = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceWidth)),
                                                                                                         DeviceHeight = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceHeight)),
                                                                                                         MergePoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Switch_MergePoint),
                                                                                                         NormalPoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Switch_NormalPoint),
                                                                                                         ReversePoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Switch_ReversePoint)
                                                                                                     }));
                    }
                    else if (deviceXML.Name.LocalName == Resource.SerializeDeviceViewModels_TrackSegment)
                    {
                        deviceViewModels.AddRange(DeviceViewModelFactory.GenerateDeviceViewModel(new TrackSegmentModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceType)
                                                                                                     },
                                                                                                     new TrackSegmentGraphModel
                                                                                                     {
                                                                                                         DeviceID = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_ID)),
                                                                                                         DeviceName = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_Name),
                                                                                                         GraphType = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_GraphType),
                                                                                                         DeviceAngle = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceAngle)),
                                                                                                         DeviceWidth = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceWidth)),
                                                                                                         DeviceHeight = int.Parse((string)deviceXML.Element(Resource.SerializeDeviceViewModels_Device_DeviceHeight)),
                                                                                                         StartPoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_TrackSegment_StartPoint),
                                                                                                         EndPoint = (string)deviceXML.Element(Resource.SerializeDeviceViewModels_TrackSegment_EndPoint),
                                                                                                     }));
                    }
                    else
                    {
                        
                    }
                }
            }

            foreach (DeviceBaseViewModel deviceViewModel in deviceViewModels)
            {
                deviceViewModel.PositionPoint = new Point(deviceViewModel.PositionPoint.X + offset.X, deviceViewModel.PositionPoint.Y + offset.Y);
            }

            return deviceViewModels;
        }

        public static XElement LoadSerializedDataFromClipBoard()
        {
            if (Clipboard.ContainsData(DataFormats.Xaml))
            {
                String clipboardData = Clipboard.GetData(DataFormats.Xaml) as String;

                if (String.IsNullOrEmpty(clipboardData))
                    return null;

                try
                {
                    return XElement.Load(new StringReader(clipboardData));
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.StackTrace, e.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

            return null;
        }
    }
}
